// vPresent is an immersive presentation creation and display application.
// Copyright (C) 2007 by Infiscape Corporation
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

#ifndef _VP_WINDOW_H_
#define _VP_WINDOW_H_

#include <string>
#include <boost/function.hpp>
#include <boost/noncopyable.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/signal.hpp>

#include "WindowSettings.h"

#if WINDOW_SYS == X11
#  include <X11/X.h>
#  include <X11/Xlib.h>
#  include <X11/Xutil.h>
#endif

#include <OpenSG/OSGConfig.h>
#include <OpenSG/OSGWindow.h>

#include "WindowPtr.h"


namespace vp
{

class Window
   : private boost::noncopyable
   , public boost::enable_shared_from_this<Window>
{
private:
   Window();

public:
   static WindowPtr create()
   {
      return WindowPtr(new Window());
   }

   WindowPtr init(int& argc, char** argv, const bool fullScreen,
                  const bool alwaysOnTop, const bool stereo,
                  const std::string& name, const int x = 0, const int y = 0,
                  const unsigned int width = 300,
                  const unsigned int height = 300);

   ~Window();

   /**
    * Retrieves the OSG::Window pointer for this window. If createWindow()
    * has not been called, the value of this will be OSG::NullFC.
    */
   const OSG::WindowRefPtr getWindow() const
   {
      return mWindow;
   }

   /** @name Render Signal */
   //@{
   typedef boost::signal<void ()> render_signal_t;
   typedef render_signal_t::slot_function_type render_slot_t;

   boost::signals::connection connectRenderSlot(render_slot_t slot);
   //@}

   /**
    * Maps the created window to the screen.
    */
   void show();

   /**
    * Hides the window but does not destroy it or any resources associated
    * with this object.
    */
   void hide();

   /**
    * Returns only when \c mDone is true.
    *
    * @see close()
    */
   void runEventLoop();

   /**
    * Sets \c mDone to true so that the event loop processing can cease. The
    * platform-specific window associated with this object is not actually
    * closed until this object is destroyed.
    *
    * @post \c mDone is true.
    */
   void close();

private:
   /**
    * Creates a platform-specific window using the parameters set when this
    * object was constructed.
    */
   const OSG::WindowRefPtr createWindow(int& argc, char** argv,
                                        const bool fullScreen,
                                        const bool alwaysOnTop,
                                        const bool stereo,
                                        const std::string& name, const int x,
                                        const int y, const unsigned int width,
                                        const unsigned int height);

   void reshape(const int width, const int height);

   OSG::WindowRefPtr mWindow;

   /** @name Window Parameters */
   //@{
   bool mFullScreen;
   int  mX;
   int  mY;
   //@}

   /** @name Event Loop Data */
   //@{
   bool mDone;
   render_signal_t mRenderSignal;
   //@}

#if WINDOW_SYS == X11
   /** @name X Window System Members */
   //@{
   Display*     mDisplay;
   Colormap     mColormap;
   ::Window     mXWindow;
   XVisualInfo* mVisualInfo;
   Cursor       mEmptyCursor;
   //@}
#endif
};

}


#endif /* _VP_WINDOW_H_ */
